package org.gikolet.ch2.android.logic;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.gikolet.ch2.dao.BoardsDao;
import org.gikolet.ch2.dao.DaoException;
import org.gikolet.ch2.dao.ThreadHeaderDao;
import org.gikolet.ch2.data.Board;
import org.gikolet.ch2.data.Res;
import org.gikolet.ch2.data.ThreadHeader;
import org.gikolet.ch2.io.ReaderType;
import org.gikolet.ch2.io.ResesReader;
import org.gikolet.ch2.io.ResesReaderProvider;
import org.gikolet.ch2.logic.ResesLogic;
import org.gikolet.util.IOUtils;

import com.google.inject.Inject;

public class AndroidResesLogic implements ResesLogic {

	private ThreadHeader threadHeaderCache;
	private List<Res> resesCache;
	private String subjectCache;

	@Inject
	private BoardsDao boardsDao;

	@Inject
	private ThreadHeaderDao threadHeaderDao;

	@Inject
	private ResesReaderProvider resesReaderProvider;

	public void update(ThreadHeader threadHeader, boolean cache)
			throws IOException {

		ReaderType readerType = cache ? ReaderType.CONNECT_CACHE
				: ReaderType.CONNECT;

		ResesReader reader = null;
		try {
			reader = this.resesReaderProvider.createResesReader(threadHeader,
					readerType);

			List<Res> reses = new ArrayList<Res>();

			Res res = null;
			String subject = null;

			while ((res = reader.read()) != null) {
				reses.add(res);

				subject = null;
			}

			synchronized (getClass()) {
				this.threadHeaderCache = threadHeader;
				this.resesCache = reses;
				this.subjectCache = subject;
			}

		} finally {
			IOUtils.closeQuietly(reader);
		}

		// TODO IDを取得する便利クラスがあってもいいかも
		try {
			ThreadHeader tmpThreadHeader = this.threadHeaderDao.find(
					threadHeader.getBoard().getHostName(), threadHeader
							.getBoard().getPath(), threadHeader.getThreadKey());

			threadHeader.setId(tmpThreadHeader.getId());
			threadHeader.getBoard().setId(tmpThreadHeader.getBoard().getId());

			this.threadHeaderDao.update(threadHeader);

		} catch (DaoException te) {
			if (te.getError() != DaoException.Error.NOT_FOUND) {
				throw te;
			}
			// みつからなかった
			try {
				// 板のIDを取得
				Board tmpBoard = this.boardsDao.findHostNameAndPath(
						threadHeader.getBoard().getHostName(), threadHeader
								.getBoard().getPath());

				threadHeader.getBoard().setId(tmpBoard.getId());

			} catch (DaoException be) {
				if (be.getError() != DaoException.Error.NOT_FOUND) {
					throw be;
				}
				// みつからなかった
				this.boardsDao.create(threadHeader.getBoard());
			}

			this.threadHeaderDao.create(threadHeader);
		}
	}

	public List<Res> getReses(ThreadHeader threadHeader) throws IOException {

		synchronized (getClass()) {
			if (threadHeader.equals(this.threadHeaderCache)) {
				// TODO 一応ここでthreadHeaderの情報全部を更新したほうがいいかも
				threadHeader.setSubject(this.subjectCache);

				return this.resesCache;
			}
		}

		ResesReader reader = this.resesReaderProvider.createResesReader(
				threadHeader, ReaderType.CACHE);

		List<Res> reses = new ArrayList<Res>();

		String subjectStr = reader.getSubject();

		Res r;
		while ((r = reader.read()) != null) {
			reses.add(r);
		}

		threadHeader.setSubject(subjectStr);

		return reses;
	}
}
